package com.yth.extension;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

import java.util.Arrays;
import java.util.List;

/**
 * bean的实例化前后
 *
 * <li>注意：<code>InstantiationAwareBeanPostProcessor extends BeanPostProcessor</code></li>
 *
 * @author yutianhong
 * @version 1.0
 * @since 2023/08/29 14:38:43
 */
@Slf4j
public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // bean实例化之前，可以在此对这个bean做代理、增强
        log.info("[InstantiationAwareBeanPostProcessor::postProcessBeforeInstantiation] \t>>> beanClass: {}, beanName: {}", beanClass.getSimpleName(), beanName);
        return null;    // 如果返回not-null，则会跳过这个bean的创建过程
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        // bean实例化之后，可以在此对bean的属性注入做定制逻辑处理
        log.info("[InstantiationAwareBeanPostProcessor::postProcessAfterInstantiation] \t>>> beanClass: {}, beanName: {}", bean.getClass().getSimpleName(), beanName);
        return true;    // 如果返回true，代表允许spring对这个bean进行后续的属性注入；返回false则代表流程直接'短路'
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        // bean实例化之后，factory进行属性注入之前
        log.info("[InstantiationAwareBeanPostProcessor::postProcessProperties] \t>>> propertyValues: {}, beanClass: {}, beanName: {}", pvs, bean.getClass().getSimpleName(), beanName);
        if (beanName.equals("testSetPropertiesBean")) {
            List<PropertyValue> propertyValues = Arrays.asList(
                    new PropertyValue("qux", "fox"),
                    new PropertyValue("testField", "modified"));
            return new MutablePropertyValues(propertyValues);
        }
        return null;
    }

}
